package org.jsets.fastboot.security.aop;

import java.lang.annotation.Annotation;
import org.aspectj.lang.JoinPoint;
import org.jsets.fastboot.util.PatternUtils;
import org.jsets.fastboot.util.StringUtils;
import org.jsets.fastboot.security.SecurityUtils;
import org.jsets.fastboot.security.annotation.HMACAuthenticate;
import org.springframework.http.HttpHeaders;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.InsufficientAuthenticationException;

/**
 * HMACAuthenticate注解方法拦截器
 *
 * @author wangjie (https://github.com/wj596)
 * @date 2021.07.10 23:56
 */
@Slf4j
public class HMACAuthenticateMethodInterceptor extends AnnotationMethodInterceptor {

	private static final String HEADER_PARAM_TIMESTAMP = "X-Timestamp";
	private static final String HEADER_PARAM_SIGN      = "X-Sign";
	
	public HMACAuthenticateMethodInterceptor(Class<? extends Annotation> annotationClass) {
		super(annotationClass);
	}

	@Override
	void doAuthenticate(JoinPoint joinPoint) throws Throwable {
		
		Annotation ann = this.getAnnotation(joinPoint);
		if (!(ann instanceof HMACAuthenticate)) {
			throw new IllegalStateException("annotation type mismatching");
		}
		
		HttpHeaders httpHeaders = null;
		Object[] args = this.getInvokeMethodArgs(joinPoint);
		for(int i=0;i<args.length;i++) {
			if(args[i] instanceof HttpHeaders) {
				httpHeaders = (HttpHeaders)args[i];
				break;
			}
		}

		if(null==httpHeaders) {
			throw new IllegalArgumentException("请在方法上注入httpHeaders参数");
		}
		
		if(!httpHeaders.containsKey(HEADER_PARAM_TIMESTAMP)) {
			throw new IllegalArgumentException("HttpHeader中没有参数X-Timestamp");
		}
		
		if(!httpHeaders.containsKey(HEADER_PARAM_SIGN)) {
			throw new IllegalArgumentException("HttpHeader中没有参数X-Sign");
		}
		
		String timestamp = httpHeaders.get(HEADER_PARAM_TIMESTAMP).get(0);
		if(!PatternUtils.isNumberic(timestamp)) {
			throw new IllegalArgumentException("HttpHeader参数X-Timestamp必须为Long类型");
		}
		String signature = httpHeaders.get(HEADER_PARAM_SIGN).get(0);
		if(StringUtils.isBlank(signature)) {
			throw new IllegalArgumentException("HttpHeader参数X-Sign不能为空");
		}
		
		log.info("HMAC签名验证，timestamp：{}，signature：{}", timestamp, signature);
		
		boolean allowed = SecurityUtils.hmacSignatureValidate(Long.valueOf(timestamp), signature);
    	if(!allowed) {
    		throw new InsufficientAuthenticationException(SecurityUtils.getProperties().getHmacInvalidTips());
    	}
	}
}
